<template>
    <div class="cvu-notification">
        <cvu-poptip
            :theme="theme"
            :trigger="trigger"
            :placement="placement"
            :width="width"
            :dis-arrow="disArrow"
            @on-popper-show="showMessageList"
        >
            <div class="cvu-notification-icon">
                <Badge :count="count" :overflow-count="overflowCount" :dot="dot" size="small">
                    <Icon type="md-notifications-outline" />
                </Badge>
            </div>
            <div slot="title">
                <div class="cvu-notification-more" @click.stop="openMessagePage">
                    查看更多>
                </div>
            </div>
            <div slot="content">
                <div class="cvu-notification-lists" v-if="data.length > 0">
                    <div class="cvu-notification-list" 
                        v-for="(item, index) in data" :key="index"
                        @click.stop="openMessagePage(item)"
                    >
                        <div class="cvu-notification-title" :title="item.title">{{ item.title }}</div>
                        <cvu-divider v-if="index != data.length - 1" />
                    </div>
                </div>
                <cvu-empty v-else :image="emptyImage" :image-size="emptyImageSize" :description="emptyDescription"></cvu-empty>
            </div>
        </cvu-poptip>
    </div>
</template>

<script>
import common from '../../../until/common'
export default {
    name: 'cvu-notification',
    props: {
        // 主题
        theme: {
            type: String,
            default: 'light'
        },
        // 触发方式，可选值为hover（悬停）click（点击）focus（聚焦）,在 confirm 模式下，只有 click 有效
        trigger: {
            type: String,
            default: 'click'
        },
        // 提示框出现的位置，可选值为
        placement: {
            validator (value) {
                return common.oneOf(value, [
                    'top', 
                    'top-start', 
                    'top-end', 
                    'bottom', 
                    'bottom-start', 
                    'bottom-end', 
                    'left', 
                    'left-start', 
                    'left-end', 
                    'right', 
                    'right-start', 
                    'right-end'
                ]);
            },
            default: 'bottom'
        },
        // 宽度，最小宽度为 150px，在 confirm 模式下，默认最大宽度为 300px
        width: {
            type: [String, Number],
            default: 240
        },
        // 是否隐藏小三角
        disArrow: {
            type: Boolean,
            default: true
        },
        // 消息数量
        count: {
            type: Number,
            default: 0
        },
        // 展示封顶的数字值
        overflowCount: {
            type: Number || String,
            default: 99
        },
        // 不展示数字，只有一个小红点，如需隐藏 dot ，需要设置count为 0
        dot: {
            type: Boolean,
            default: false
        },
        // websocket url地址
        websockUrl: {
            type: String,
            default: ''
        },
        // 消息数据 [ { id: '', title: '' } ]
        data: {
            type: Array,
            default: () => {}
        },
        // 消息列表空数据提示图片
        emptyImage: {
            type: String,
            default: ''
        },
        // 消息列表空数据提示图片大小
        emptyImageSize: {
            type: Number,
            default: 100
        },
        // 消息列表空数据提示文字
        emptyDescription: {
            type: String,
            default: '暂无消息'
        }
    },
    data() {
        return {
            websock: null,
            // 是否真正建立连接
            lockReconnect: false,
            // 心跳计时器
            pantTimer: null,
            // 30秒一次心跳
            pantTime: 30 * 1000, 
            // 重连计时器
            reconnectTimer: null,
            // 重连间隔时间
            reconnectTime: 20 * 1000,
            // 超时关闭计时器
            overTimer: null,
            // 是否离开页面
            leavePage: false
        }
    },
    destroyed() {
        this.leavePage = true
        this.websock ? this.websock.close() : '' // 离开路由之后断开websocket连接
    },
    mounted() {
        // websocket 初始化
        this.websocketInit()
    },
    methods: {
        // 点击消息图标 => 展示消息列表弹窗
        showMessageList() {
            this.$emit('on-show')
        },
        // 点击消息列表 / 查看更多 => 进入消息页面
        openMessagePage(item = {}) {
            this.$emit('on-click', item)
        },
        // websocket 初始化
        websocketInit() {
            return new Promise((resolve, reject) => {
                if(!this.websockUrl) {
                    return
                }
                this.websock = new WebSocket(this.websockUrl)
                this.websock.onmessage = this.websocketOnMessage
                this.websock.onopen = this.websocketOnOpen
                this.websock.onerror = this.websocketOnError
                this.websock.onclose = this.websocketClose
                this.$nextTick(() => {
                    resolve()
                })
            })
        },
        // websocket 重新连接
        websockReconnect() {
            return new Promise((resolve, reject) => {
                if(this.lockReconnect) {
                    return
                }
                this.lockReconnect = true
                this.reconnectTimer && clearTimeout(this.reconnectTimer)
                this.reconnectTimer = setTimeout(() => {
                    this.websocketInit()
                    this.lockReconnect = false
                    this.$nextTick(() => {
                        resolve()
                    })
                }, this.reconnectTime)
            })
        },
        // websocket 开启心跳
        websockPantStart() {
            return new Promise((resolve, reject) => {
                this.pantTimer && clearTimeout(this.pantTimer)
                this.overTimer && clearTimeout(this.overTimer)
                this.pantTimer = setTimeout(() => {
                    // 这里发送一个心跳，后端收到后，返回一个心跳消息，
                    if (this.websock.readyState == 1) {
                        // 如果连接正常
                        this.websock.send('心跳')
                    } else {
                        // 否则重连
                        this.reconnect()
                    }
                    this.overTimer = setTimeout(() => {
                        // 超时关闭
                        this.websock.close()
                    }, this.pantTime)
                    this.$nextTick(() => {
                        resolve()
                    })
                }, this.pantTime)
            })
        },
        // websocket 重置心跳
        websockReset() {
            // 清除时间
            clearTimeout(that.pantTimer)
            clearTimeout(that.overTimer)
            // 重启心跳
            that.start()
        },
        // websocket 连接成功
        websocketOnOpen(e) {
            // 开启心跳
            this.websockPantStart()
        },
        // websocket 连接失败
        websocketOnError(e) {
            // 重新连接
            this.websockReconnect()
        },
        // websocket 关闭
        websocketClose(e) {
            if (!this.leavePage) {
                this.websockReconnect()
            }
        },
        // websocket 接收服务器推送的信息
        websocketOnMessage(e) {
            this.$emit('on-message', e)
            // 接收到消息后重置心跳
            this.websockReset()
        },
        // websocket 向服务器发送信息
        websocketOnSend(msg) {
            this.websock.send(msg)
        }
    }
}
</script>
<style lang="scss" scoped>
@import '../../../style/_index.scss';
.cvu-notification{
    display: inline-block;
    width: 30px;
    height: 30px;
    .cvu-notification-icon{
        cursor: pointer;
        /deep/.ivu-icon{
            font-size: 28px;
        }
        /deep/.ivu-badge-count{
            zoom: .8;
        }
    }
    .cvu-notification-more{
        display: flex;
        justify-content: flex-end;
        align-items: center;
        font-size: 14px;
        color: #333;
        transition: all .2s;
        cursor: pointer;
        &:hover{
            color: $primary-blue;
        }
    }
    .cvu-notification-lists{
        .cvu-notification-list{
            padding: 0 10px;
            box-sizing: border-box;
            transition: all .2s;
            cursor: pointer;
            &:hover{
                background: #F5F5F5;
                .cvu-notification-title{
                    color: $primary-blue;
                }
            }
            .cvu-notification-title{
                width: 100%;
                height: 40px;
                line-height: 40px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                font-size: 14px;
                color: #333;
                transition: all .2s;
            }
        }
    }
}
</style>